package com.romejiang;


import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import io.socket.engineio.client.transports.WebSocket;
import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.json.JSONObject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@SpringBootApplication
public class Application {

    public static String plotFileNamePattern = ".*(\\d{14,25})_\\d+_\\d+";


    public static void main(String[] args) throws IOException {




//        getMac();

//         String mac = getMacAddress();
//         System.out.println(mac);
//        try {
//            IO.Options options = new IO.Options();
//            options.transports = new String[]{WebSocket.NAME};
//            Socket socket = IO.socket("http://localhost:7001",options);
//
//            socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
//
//                @Override
//                public void call(Object... args) {
//                    System.out.println("connecting..");
////                    socket.emit("foo", "hi");
////                    socket.disconnect();
//                }
//
//            }).on("miner", new Emitter.Listener() {
//
//                @Override
//                public void call(Object... args) {
//                    JSONObject obj = (JSONObject)args[0];
//                    System.out.println(obj);
//                }
//
//            }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
//
//                @Override
//                public void call(Object... args) {
//                }
//
//            });
//            socket.connect();
//        } catch (URISyntaxException e) {
//            e.printStackTrace();
//        }

//        String name = "/Users/stephen/plotter/5723676911382306858_0_163840";
//
//        String string[] = {"/Users/stephen/plotter/5723676911382306858_0_163840",
//                "/Users/ste phen/plotter/5723676911382306858_163840_184320",
//        "5723676911382306858_0_163840"};
//
//        for (String str :string) {
//            find(str);
//        }

//        SpringApplication.run(Application.class, args);
//        assert (getBlockReward(0)) == 0;
//        System.out.println(getBlockReward(525000 - 1));
//        System.out.println(getBlockReward(525000));
//        for (int x = 1; x < 33; x++) {
//            int height = x * 525000 + 1;
//
//
//            System.out.println(getBlockReward(height));
//        }
//
//        System.out.println(getBlockReward(17325000 + 1));

//        disks();

//        traverFile3(new File("/Users/stephen/data"));


//       Application app =  new Application();

//       app.search();


        Map<String, Collection<Path>> plotFilesLookup = disks();
        for (Map.Entry<String, Collection<Path>> entry : plotFilesLookup.entrySet()) {
            System.out.println( entry.getKey());
            System.out.println(entry.getValue());
        }
    }

    public static Map<String, Collection<Path>> getNonceSources(File startDirectory) throws IOException {
        final List<File> ruleFiles = new ArrayList<>();

        FileFilter fileFilter = new RegexFileFilter(plotFileNamePattern);
        new DirectoryWalker<File>(null, (IOFileFilter) fileFilter,3) {
            @Override
            protected void handleFile(File file, int depth, Collection<File> results) throws IOException {
                    results.add(file);
            }
            public void scan(File directory) throws IOException {
                super.walk(directory, ruleFiles);
            }
        }.scan(startDirectory);
        Map<String, Collection<Path>> plotFilesLookup = new HashMap<>();
        for (File ruleFile : ruleFiles) {
            String parent = ruleFile.getParent();
            Collection<Path> lists = plotFilesLookup.get(parent);
            if (lists == null){
                lists = new ArrayList<>();
            }
            lists.add(ruleFile.toPath());
            plotFilesLookup.put(parent, lists);
        }
        return plotFilesLookup;
    }


    public void search(){
        System.out.println("search...");
        FileFilter fileFilter = new RegexFileFilter(plotFileNamePattern);

        File dir = new File("/Users/stephen/plotter");
        File[] files = dir.listFiles(fileFilter);
        for (int i = 0; i < files.length; i++) {
            System.out.println(files[i]);
        }
        // Use the filters to construct the walker
        FooDirectoryWalker walker = new FooDirectoryWalker(
                fileFilter
        );

        try {
            List files2 = walker.clean(new File("/Users/stephen/plotter"));
            for (Object tmpFile : files2) {
                 System.out.println(tmpFile.toString());
            }
            } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public class FooDirectoryWalker extends DirectoryWalker {
        public FooDirectoryWalker(FileFilter filter) {
            super( filter, -1);
        }
        public List clean(File startDirectory) throws IOException {
            System.out.println("search...");
            List results = new ArrayList();
            walk(startDirectory, results);
            System.out.println("search..." + results.size());
            return results;
        }
    }


    private static int depth=1;

    public static void find(String pathName,int depth) throws IOException {
        int filecount=0;
        //获取pathName的File对象
        File dirFile = new File(pathName);
        //判断该文件或目录是否存在，不存在时在控制台输出提醒
        if (!dirFile.exists()) {
            System.out.println("do not exit");
            return ;
        }
        //判断如果不是一个目录，就判断是不是一个文件，时文件则输出文件路径
        if (!dirFile.isDirectory()) {
            if (dirFile.isFile()) {
                System.out.println(dirFile.getCanonicalFile());
            }
            return ;
        }
        for (int j = 0; j < depth; j++) {
            System.out.print("  ");
        }
        System.out.print("|--");
        System.out.println(dirFile.getName());
        //获取此目录下的所有文件名与目录名
        String[] fileList = dirFile.list();
        int currentDepth=depth+1;
        for (int i = 0; i < fileList.length; i++) {
            //遍历文件目录
            String string = fileList[i];
            //File("documentName","fileName")是File的另一个构造器
            File file = new File(dirFile.getPath(),string);
            String name = file.getName();
            //如果是一个目录，搜索深度depth++，输出目录名后，进行递归
            if (file.isDirectory()) {
                //递归
                find(file.getCanonicalPath(),currentDepth);
            }else{
                //如果是文件，则直接输出文件名
                for (int j = 0; j < currentDepth; j++) {
                    System.out.print("  ");
                }
                System.out.print("|--");
                System.out.println(name);
            }
        }
    }

    private static void traverFile3(File file) {
        int depth = 0;
        LinkedList<File> list = new LinkedList<>();
        list.push(file);
        while (!list.isEmpty()) {
            File f = list.pop();
            System.out.println(f);
            if(depth < 2) {
                File[] files = f.listFiles();
                if (files != null) {
                    depth++;
                    for (File fil : files) {
                        list.push(fil);
                    }
                }
            }
        }
    }

    public static Map<String, Collection<Path>> disks(){
        // 获取磁盘分区列表
        LinkedList<File> roots = new LinkedList<>(Arrays.asList(File.listRoots()));

        roots.add(new File( System.getProperty("user.home")));
        Map<String, Collection<Path>> total =  new HashMap<>();
        for (File file : roots) {
            try {
                System.out.println(file);
                Map<String, Collection<Path>> plotFilesLookup = getNonceSources(file);
                total.putAll(plotFilesLookup);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  total;
    }

    public static long change(long num) {
        // return num;
        return num / 1024 / 1024 / 1024;
    }

    public static String bfb(Object num1, Object num2) {
        double val1 = Double.valueOf(num1.toString());
        double val2 = Double.valueOf(num2.toString());
        if (val2 == 0) {
            return "0.0%";
        } else {
            DecimalFormat df = new DecimalFormat("#0.00");
            return df.format(val1 / val2 * 100) + "%";
        }
    }

    /**
     * 按照"XX-XX-XX-XX-XX-XX"格式，获取本机MAC地址
     * @return
     * @throws Exception
     */
    public static String getMacAddress() {
        try {
        Enumeration<NetworkInterface> ni = NetworkInterface.getNetworkInterfaces();

        while(ni.hasMoreElements()){
            NetworkInterface netI = ni.nextElement();

            byte[] bytes = netI.getHardwareAddress();
            if(netI.isUp() && netI != null && bytes != null && bytes.length == 6){
                StringBuffer sb = new StringBuffer();
                for(byte b:bytes){
                    //与11110000作按位与运算以便读取当前字节高4位
                    sb.append(Integer.toHexString((b&240)>>4));
                    //与00001111作按位与运算以便读取当前字节低4位
                    sb.append(Integer.toHexString(b&15));
                    sb.append("-");
                }
                sb.deleteCharAt(sb.length()-1);
                return sb.toString().toUpperCase();
            }
        } } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }



    public static String getMac() {
        InetAddress ip;
        StringBuilder sb = new StringBuilder();
        try {
            ip = InetAddress.getLocalHost();
            System.out.println(ip);
            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
            System.out.println(network);
            byte[] mac = network.getHardwareAddress();
            System.out.println(mac);
            sb = new StringBuilder();
            for (int i = 0; i < mac.length; i++) {
                sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return sb.toString();
    }

    public static final long ONE_BURST = 100000000;

    public static long getBlockReward(int height) {
        if (height == 0) {
            return 0;
        }
        if (height >= 17325000) {
            return 0;
        }
        int month = (height - 1) / 525000;
        BigInteger reward = BigInteger.valueOf(20).multiply(BigInteger.valueOf(ONE_BURST * 10));
        System.out.println(height + " / " + (month + 1));
        for (int round = 0; round < month; round++) {
            reward = reward.divide(BigInteger.valueOf(2));
        }
        return Math.round(Math.ceil(reward.doubleValue() / 10));
    }

    public static void find(String name) {

        String pattern = ".*(\\d{18,22})_\\d+_\\d+";
        boolean isMatch = Pattern.matches(pattern, name);
        System.out.println(name);
        System.out.println(isMatch);

        Matcher m = Pattern.compile(pattern).matcher(name);
        if (m.find()) {
            System.out.println("Found value: " + m.group(1));
        }
        System.out.println("==========================");
    }
}